using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
using Alerter.DataSet;
using DevExpress.Utils;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using E4RPTools;

namespace Alerter.Controls
{
    public partial class MessageXtraForm : XtraForm
    {
        private long _documentId;
        private Controller _controller;
        private MensagemDataSet _dataSet;
        private bool _loading;
        
        #region Properties

        public long DocumentId
        {
            set { _documentId = value; }
        }

        public Controller Controller
        {
            set { _controller = value; }
        }

        #endregion

        public MessageXtraForm()
        {
            InitializeComponent();
            Load += MessageXtraFormLoad;
            contactsSimpleButton.Click += ContactsSimpleButtonClick;
            okSimpleButton.Click += OkSimpleButtonClick;
            gridView.InitNewRow += GridViewInitNewRow;
            messageTypeLookUpEdit.EditValueChanged += MessageTypeLookUpEditEditValueChanged;
            toolTipController.GetActiveObjectInfo += ToolTipControllerGetActiveObjectInfo;
        }
        
        #region Private Methods

        private void SetupGroupLookupData()
        {
            grupoDataSet = _controller.GetGroups();
            groupRepositoryItemLookUpEdit.Columns.Clear();
            groupRepositoryItemLookUpEdit.Columns.AddRange(new[] {
                new LookUpColumnInfo("Id", "Id", 81, FormatType.None, "", false, HorzAlignment.Near),
                new LookUpColumnInfo("Nome", "Nome", 85, FormatType.None, "", true, HorzAlignment.Near)});
            groupRepositoryItemLookUpEdit.DisplayMember = grupoDataSet.Grupo.NomeColumn.ColumnName;
            groupRepositoryItemLookUpEdit.ValueMember = grupoDataSet.Grupo.IdColumn.ColumnName;
            groupRepositoryItemLookUpEdit.DataSource = grupoDataSet.Grupo;
        }

        private void SetupContactLookupData()
        {
            contactoDataSet = _controller.GetContacts();
            contactRepositoryItemLookUpEdit.Columns.Clear();
            contactRepositoryItemLookUpEdit.Columns.AddRange(new[] {
                new LookUpColumnInfo("Id", "Id", 81, FormatType.None, "", false, HorzAlignment.Near),
                new LookUpColumnInfo("Nome", "Nome", 85, FormatType.None, "", true, HorzAlignment.Near)});
            contactRepositoryItemLookUpEdit.DisplayMember = contactoDataSet.Contacto.NomeColumn.ColumnName;
            contactRepositoryItemLookUpEdit.ValueMember = contactoDataSet.Contacto.IdColumn.ColumnName;
            contactRepositoryItemLookUpEdit.DataSource = contactoDataSet.Contacto;            
        }

        private void SetupMessageTypeLookupData()
        {
            tipoMensagemDataSet = _controller.GetMessageTypes();
            messageTypeLookUpEdit.Properties.Columns.Clear();
            messageTypeLookUpEdit.Properties.Columns.AddRange(new[] {
                new LookUpColumnInfo("Id", "Id", 81, FormatType.None, "", false, HorzAlignment.Near),
                new LookUpColumnInfo("Nome", "Nome", 85, FormatType.None, "", true, HorzAlignment.Near)});
            messageTypeLookUpEdit.Properties.DisplayMember = tipoMensagemDataSet.TipoMensagem.NomeColumn.ColumnName;
            messageTypeLookUpEdit.Properties.ValueMember = tipoMensagemDataSet.TipoMensagem.IdColumn.ColumnName;
            messageTypeLookUpEdit.Properties.DataSource = tipoMensagemDataSet.TipoMensagem;            
        }

        private void MergeData()
        {
            _dataSet = new MensagemDataSet();
            if (_documentId <= 0)
            {
                var message = _dataSet.Mensagem.NewMensagemRow();
                message.Id = _documentId;
                message.Data = DateTime.Now;
                message.Descricao = "";
                message.Estado = MessageState.AEnviar.ToString();
                message.Unicode = true;
                _dataSet.Mensagem.AddMensagemRow(message);
            }
            else
                _dataSet.Merge(_controller.GetMessage(_documentId));
        }

        private void GetDataFromControls()
        {

            var dateTime = new DateTime(Convert.ToDateTime(dateEdit.EditValue).Year,
                                        Convert.ToDateTime(dateEdit.EditValue).Month,
                                        Convert.ToDateTime(dateEdit.EditValue).Day,
                                        Convert.ToDateTime(timeEdit.EditValue).Hour,
                                        Convert.ToDateTime(timeEdit.EditValue).Minute,
                                        Convert.ToDateTime(timeEdit.EditValue).Second);
            
            _dataSet.Mensagem[0].Data = dateTime;
            if (messageTypeLookUpEdit.EditValue == null)
                _dataSet.Mensagem[0].SetIdTipoMensagemNull();
            else
                _dataSet.Mensagem[0].IdTipoMensagem = Convert.ToInt64(messageTypeLookUpEdit.EditValue);
            _dataSet.Mensagem[0].Descricao = descriptionMemoEdit.Text;
            _dataSet.Mensagem[0].Unicode = unicodeCheckEdit.Checked; 
            gridView.CloseEditor();
            gridView.UpdateCurrentRow();
        }

        private void SetDataToControls()
        {
            dateEdit.EditValue = _dataSet.Mensagem[0].Data;
            timeEdit.EditValue = _dataSet.Mensagem[0].Data;
            if(_dataSet.Mensagem[0].IsIdTipoMensagemNull())
                messageTypeLookUpEdit.EditValue = -1;
            else
                messageTypeLookUpEdit.EditValue = _dataSet.Mensagem[0].IdTipoMensagem;
            descriptionMemoEdit.Text = _dataSet.Mensagem[0].Descricao;
            unicodeCheckEdit.Checked = _dataSet.Mensagem[0].Unicode;
            gridControl.DataSource = null;
            gridControl.DataMember = "";
            gridControl.DataSource = _dataSet.Contacto; 
        }

        private void ClearControlErrors()
        {
            dxErrorProvider.SetError(messageTypeLookUpEdit, "");
            dxErrorProvider.SetError(descriptionMemoEdit, "");            
        }

        private Control GetControl(string reference)
        {
            switch (reference)
            {
                case "Data":
                    return dateEdit;
                case "IdTipoMensagem":
                    return messageTypeLookUpEdit;
                case "Descricao":
                    return descriptionMemoEdit;
                default:
                    return null;
            }
        }

        private void SetControlErrors(Result result)
        {
            foreach (var error in result.Errors)
                dxErrorProvider.SetError(GetControl(error.Reference), error.Message);
        }

        private void LockControls()
        {
            dateEdit.Enabled = false;
            timeEdit.Enabled = false;
            messageTypeLookUpEdit.Enabled = false;
            descriptionMemoEdit.Enabled = false;
            gridControl.EmbeddedNavigator.Buttons.Remove.Enabled = false;
            contactsSimpleButton.Enabled = false;
        }

        private List<long> GetSelectedGroups()
        {
            var selectedIds = new List<long>();
            foreach(MensagemDataSet.ContactoRow contact in _dataSet.Contacto)
            {
                if(contact.RowState == DataRowState.Deleted)
                    continue;
                if (!contact.IsIdGrupoNull() && !selectedIds.Contains(contact.IdGrupo))
                    selectedIds.Add(contact.IdGrupo);
            }
            return selectedIds;
        }

        private List<long> GetSelectedContacts()
        {
            var selectedIds = new List<long>();
            foreach (MensagemDataSet.ContactoRow contact in _dataSet.Contacto)
            {
                if (contact.RowState == DataRowState.Deleted)
                    continue;
                if (!contact.IsIdContactoNull() && contact.IsIdGrupoNull() && !selectedIds.Contains(contact.IdContacto))
                    selectedIds.Add(contact.IdContacto);
            }
            return selectedIds;
        }

        private void DeleteContacts()
        {
            var contacts = new List<MensagemDataSet.ContactoRow>();
            foreach (MensagemDataSet.ContactoRow contact in _dataSet.Contacto)
                contacts.Add(contact);
            foreach(var contact in contacts)
                contact.Delete();
        }

        private void AddGroupContacts(long groupId)
        {
            var contacts = _controller.GetGroup(groupId);
            foreach(GrupoDataSet.ContactoRow contact in contacts.Contacto)
            {
                var newContact = _dataSet.Contacto.NewContactoRow();
                newContact.IdMensagem = _dataSet.Mensagem[0].Id;
                newContact.IdGrupo = groupId;
                newContact.IdContacto = contact.IdContacto;
                newContact.Estado = MessageState.AEnviar.ToString();
                _dataSet.Contacto.AddContactoRow(newContact);
            }            
        }

        private void ShowContactsCount()
        {
            countCalcEdit.EditValue = _dataSet.Contacto.Count;
        }

        #endregion

        void MessageXtraFormLoad(object sender, EventArgs e)
        {
            _loading = true;
            MergeData();
            SetupMessageTypeLookupData();
            SetupGroupLookupData();
            SetupContactLookupData();
            SetDataToControls();
            ShowContactsCount();
            if (_dataSet.Mensagem[0].Estado == MessageState.Enviada.ToString()) LockControls();            
            _loading = false;
        }

        void OkSimpleButtonClick(object sender, EventArgs e)
        {
            ClearControlErrors();
            GetDataFromControls();
            var result = _controller.IsMessageValid(_dataSet);
            if (result.Failed)
            {
                DialogResult = DialogResult.None;
                SetControlErrors(result);
            }
            else
                _controller.SaveMessage(_dataSet);
        }

        void GridViewInitNewRow(object sender, DevExpress.XtraGrid.Views.Grid.InitNewRowEventArgs e)
        {
            var contact = (MensagemDataSet.ContactoRow)gridView.GetDataRow(e.RowHandle);
            contact.IdMensagem = _dataSet.Mensagem[0].Id;
            contact.Estado = "AEnviar";
        }

        void MessageTypeLookUpEditEditValueChanged(object sender, EventArgs e)
        {
            if (_loading) return;
            descriptionMemoEdit.Text = tipoMensagemDataSet.TipoMensagem.FindById(Convert.ToInt64(messageTypeLookUpEdit.EditValue)).Descricao;
        }

        void ContactsSimpleButtonClick(object sender, EventArgs e)
        {
            gridView.CloseEditor();
            gridView.UpdateCurrentRow();
            var messageContact = new MessageContactXtraForm
                                     {
                                         Controller = _controller,
                                         SelectedGroups = GetSelectedGroups(),
                                         SelectedContacts = GetSelectedContacts()
                                     };
            if(messageContact.ShowDialog() != DialogResult.OK)
                return;
            DeleteContacts();
            foreach (var selectedGroup in messageContact.SelectedGroups)
                AddGroupContacts(selectedGroup);
            foreach (var selectedContact in messageContact.SelectedContacts)
            {
                var contact = _dataSet.Contacto.NewContactoRow();
                contact.IdMensagem = _dataSet.Mensagem[0].Id;
                contact.IdContacto = selectedContact;
                contact.Estado = MessageState.AEnviar.ToString();
                _dataSet.Contacto.AddContactoRow(contact);
            }
            ShowContactsCount();
        }

        void ToolTipControllerGetActiveObjectInfo(object sender, ToolTipControllerGetActiveObjectInfoEventArgs e)
        {
            if(gridView.FocusedColumn != colEstado)
                return;
            var dataRow = gridView.GetDataRow(gridView.FocusedRowHandle);
            if(dataRow == null)
                return;
            var contact = (MensagemDataSet.ContactoRow)dataRow;
            toolTipController.ShowHint(contact.IsResultadoNull() ? "" : contact.Resultado);            
        }

    }
}